﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cinch;
using System.ComponentModel;
using System.ComponentModel.Composition;

namespace Anata.Client
{
    /// <summary>
    /// Represents a single Image ViewModel
    /// </summary>
    public class TransaksiLayananViewModel : EditableValidatingViewModelBase
    {
        #region Data

        private ViewMode currentViewMode = ViewMode.AddMode;

        #region Data.Primitives
        private DataWrapper<Int32> idTransaksiLayanan;
        private DataWrapper<Int32?> idTransaksi;
        private String namaKonsumen;
        private DataWrapper<Int32?> idLayanan;
        private String namaLayanan;
        private Int32 hargaLayanan;
        private DataWrapper<Int32?> idKaryawan;
        private String namaKaryawan;
        private Int32 komisiKaryawan;
        private DataWrapper<String> namaPromo;
        private DataWrapper<Int32> potonganPromo;
        private DataWrapper<String> namaFreeGift;
        private DataWrapper<Int32?> idJenisStok;
        private String namaJenisStok;
        private DataWrapper<Int32> jumlahFreeGift;
        private DataWrapper<Int32> nilaiKepuasan;
        private DataWrapper<DateTime?> waktuBuat;
        private DataWrapper<DateTime?> waktuTunggu;
        private DataWrapper<DateTime?> waktuMulai;
        private DataWrapper<DateTime?> waktuSelesai;
        private DataWrapper<Boolean> isBatal;

        private bool isBusy = false;
        private int previousStatusTransaksiLayanan;
        #endregion

        private IEnumerable<DataWrapperBase> cachedListOfDataWrappers;

        #region Data.Rules
        private static SimpleRule idKaryawanRule;
        private static SimpleRule idLayananRule;
        #endregion

        #region Data.VMs
        #endregion

        #region Data.Services
        private IMessageBoxService messageBoxService;
        private IUIVisualizerService uiVisualizerService;
        private IReferenceProvider referenceProvider;
        #endregion

        #endregion

        #region Constructor
        [ImportingConstructor]
        public TransaksiLayananViewModel(
            IMessageBoxService messageBoxService,
            IUIVisualizerService uiVisualizerService,
            IReferenceProvider referenceProvider)
        {
            #region Constructor.SetupServices
            this.messageBoxService = messageBoxService;
            this.uiVisualizerService = uiVisualizerService;
            this.referenceProvider = referenceProvider;
            #endregion

            #region Constructor.SetupCommands
            CabangLayananSelectCommand = new SimpleCommand<Object, Object>(CanExecuteCabangLayananSelectCommand, ExecuteCabangLayananSelectCommand);
            KaryawanSelectCommand = new SimpleCommand<Object, Object>(CanExecuteKaryawanSelectCommand, ExecuteKaryawanSelectCommand);
            PromoSelectCommand = new SimpleCommand<Object, Object>(CanExecutePromoSelectCommand, ExecutePromoSelectCommand);
            FreeGiftSelectCommand = new SimpleCommand<Object, Object>(CanExecuteFreeGiftSelectCommand, ExecuteFreeGiftSelectCommand);
            TransaksiLayananPreviousCommand = new SimpleCommand<Object, Object>(CanExecuteTransaksiLayananPreviousCommand, ExecuteTransaksiLayananPreviousCommand);
            TransaksiLayananNextCommand = new SimpleCommand<Object, Object>(CanExecuteTransaksiLayananNextCommand, ExecuteTransaksiLayananNextCommand);
            TransaksiLayananCancelCommand = new SimpleCommand<Object, Object>(CanExecuteTransaksiLayananCancelCommand, ExecuteTransaksiLayananCancelCommand);
            #endregion

            #region Constructor.CreateDataWrappers
            IdTransaksiLayanan = new DataWrapper<Int32>(this, idTransaksiLayananChangeArgs);
            IdTransaksiLayanan.IsEditable = true;
            IdTransaksi = new DataWrapper<Int32?>(this, idTransaksiChangeArgs);
            IdTransaksi.IsEditable = true;
            IdLayanan = new DataWrapper<Int32?>(this, idLayananChangeArgs);
            IdLayanan.IsEditable = true;
            //NamaLayanan = new DataWrapper<String>(this, namaLayananChangeArgs);
            //NamaLayanan.IsEditable = true;
            //HargaLayanan = new DataWrapper<Int32?>(this, hargaLayananChangeArgs, HargaLayananChangeCallback);
            //HargaLayanan.IsEditable = true;
            IdKaryawan = new DataWrapper<Int32?>(this, idKaryawanChangeArgs);
            IdKaryawan.IsEditable = true;
            //NamaKaryawan = new DataWrapper<String>(this, namaKaryawanChangeArgs);
            //NamaKaryawan.IsEditable = true;
            //KomisiKaryawan = new DataWrapper<Int32?>(this, komisiKaryawanChangeArgs);
            //KomisiKaryawan.IsEditable = true;
            NamaPromo = new DataWrapper<String>(this, namaPromoChangeArgs);
            NamaPromo.IsEditable = true;
            PotonganPromo = new DataWrapper<Int32>(this, potonganPromoChangeArgs, PotonganPromoChangeCallback);
            PotonganPromo.IsEditable = true;
            NilaiKepuasan = new DataWrapper<Int32>(this, nilaiKepuasanChangeArgs);
            NilaiKepuasan.IsEditable = true;
            NamaFreeGift = new DataWrapper<String>(this, namaFreeGiftChangeArgs);
            NamaFreeGift.IsEditable = true;
            IdJenisStok = new DataWrapper<Int32?>(this, idJenisStokChangeArgs);
            IdJenisStok.IsEditable = true;
            //NamaJenisStok = new DataWrapper<String>(this, namaJenisStokChangeArgs);
            //NamaJenisStok.IsEditable = true;
            JumlahFreeGift = new DataWrapper<Int32>(this, jumlahFreeGiftChangeArgs);
            JumlahFreeGift.IsEditable = true;
            WaktuBuat = new DataWrapper<DateTime?>(this, waktuBuatChangeArgs);
            WaktuBuat.IsEditable = true;
            WaktuBuat.DataValue = DateTime.Now;
            WaktuTunggu = new DataWrapper<DateTime?>(this, waktuTungguChangeArgs, WaktuTungguChangeCallback);
            WaktuTunggu.IsEditable = true;
            WaktuMulai = new DataWrapper<DateTime?>(this, waktuMulaiChangeArgs, WaktuMulaiChangeCallback);
            WaktuMulai.IsEditable = true;
            WaktuSelesai = new DataWrapper<DateTime?>(this, waktuSelesaiChangeArgs, WaktuSelesaiChangeCallback);
            WaktuSelesai.IsEditable = true;
            IsBatal = new DataWrapper<Boolean>(this, isBatalChangeArgs, IsBatalChangeCallback);
            IsBatal.IsEditable = true;
            isBatal.DataValue = false;
            #endregion

            //fetch list of all DataWrappers, so they can be used again later without the
            //need for reflection
            cachedListOfDataWrappers =
                DataWrapperHelper.GetWrapperProperties<TransaksiLayananViewModel>(this);

            #region Create Validation Rules
            idKaryawan.AddRule(idKaryawanRule);
            idLayanan.AddRule(idLayananRule);
            #endregion

            #region Constructor.SetupCollections
            #endregion
        }
        #endregion

        #region Static
        static TransaksiLayananViewModel() {
            idKaryawanRule = new SimpleRule("DataValue", "IdKaryawan tidak valid",
	            (Object domainObject) =>
	            {
		            DataWrapper<Int32?> obj = (DataWrapper<Int32?>)domainObject;
		            return obj.DataValue == null;
	            });
            idLayananRule = new SimpleRule("DataValue", "IdLayanan tidak valid",
	            (Object domainObject) =>
	            {
		            DataWrapper<Int32?> obj = (DataWrapper<Int32?>)domainObject;
		            return obj.DataValue == null;
	            });
        }

        public static int STATUS_TRANSAKSILAYANAN_UNKNOWN = 0;
        public static int STATUS_TRANSAKSILAYANAN_CREATED = 1;
        public static int STATUS_TRANSAKSILAYANAN_WAIT = 2;
        public static int STATUS_TRANSAKSILAYANAN_BUSY = 3;
        public static int STATUS_TRANSAKSILAYANAN_FINISHED = 4;
        public static int STATUS_TRANSAKSILAYANAN_CANCELLED = 99;
        #endregion

        #region Public Properties

        #region Public.Commands
        public SimpleCommand<Object, Object> CabangLayananSelectCommand { get; private set; }
        public SimpleCommand<Object, Object> KaryawanSelectCommand { get; private set; }
        public SimpleCommand<Object, Object> PromoSelectCommand { get; private set; }
        public SimpleCommand<Object, Object> FreeGiftSelectCommand { get; private set; }
        public SimpleCommand<Object, Object> TransaksiLayananPreviousCommand { get; private set; }
        public SimpleCommand<Object, Object> TransaksiLayananNextCommand { get; private set; }
        public SimpleCommand<Object, Object> TransaksiLayananCancelCommand { get; private set; }
        #endregion

        #region Public.ViewMode
        /// <summary>
        /// The current ViewMode, when changed will loop
        /// through all nested DataWrapper objects and change
        /// their state also
        /// </summary>

        static PropertyChangedEventArgs currentViewModeChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.CurrentViewMode);

        public ViewMode CurrentViewMode
        {
            get { return currentViewMode; }
            set
            {
                currentViewMode = value;

                switch (currentViewMode)
                {
                    case ViewMode.AddMode:
                        this.DisplayName = "Transaksi Baru";
                        break;
                    case ViewMode.EditMode:
                        this.DisplayName = "Ubah Transaksi";
                        break;
                    case ViewMode.ViewOnlyMode:
                        this.DisplayName = "Lihat Transaksi";
                        break;
                }

                //Now change all the CachedListOfDataWrappers
                //Which sets all the Cinch.DataWrapper<T>s to the correct IsEditable
                //state based on the new ViewMode applied to the ViewModel
                //we can use the Cinch.DataWrapperHelper class for this
                DataWrapperHelper.SetMode(
                    CachedListOfDataWrappers,
                    currentViewMode);

                NotifyPropertyChanged(currentViewModeChangeArgs);
            }
        }
        #endregion

        #region Public.Data
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idTransaksiLayananChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.IdTransaksiLayanan);
        public DataWrapper<Int32> IdTransaksiLayanan
        {
            get { return idTransaksiLayanan; }
            set
            {
                idTransaksiLayanan = value;
                NotifyPropertyChanged(idTransaksiLayananChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idTransaksiChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.IdTransaksi);
        public DataWrapper<Int32?> IdTransaksi
        {
            get { return idTransaksi; }
            set
            {
                idTransaksi = value;
                NotifyPropertyChanged(idTransaksiChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaKonsumenChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.NamaKonsumen);
        public String NamaKonsumen
        {
            get { return namaKonsumen; }
            set
            {
                namaKonsumen = value;
                NotifyPropertyChanged(namaKonsumenChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idLayananChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.IdLayanan);
        public DataWrapper<Int32?> IdLayanan
        {
            get { return idLayanan; }
            set
            {
                idLayanan = value;
                NotifyPropertyChanged(idLayananChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaLayananChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.NamaLayanan);
        public String NamaLayanan
        {
            get { return namaLayanan; }
            set
            {
                namaLayanan = value;
                NotifyPropertyChanged(namaLayananChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs hargaLayananChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.HargaLayanan);
        public Int32 HargaLayanan
        {
            get { return hargaLayanan; }
            set
            {
                hargaLayanan = value;
                NotifyPropertyChanged(hargaLayananChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idKaryawanChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.IdKaryawan);
        public DataWrapper<Int32?> IdKaryawan
        {
            get { return idKaryawan; }
            set
            {
                idKaryawan = value;
                NotifyPropertyChanged(idKaryawanChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaKaryawanChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.NamaKaryawan);
        public String NamaKaryawan
        {
            get { return namaKaryawan; }
            set
            {
                namaKaryawan = value;
                NotifyPropertyChanged(namaKaryawanChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs komisiKaryawanChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.KomisiKaryawan);
        public Int32 KomisiKaryawan
        {
            get { return komisiKaryawan; }
            set
            {
                komisiKaryawan = value;
                NotifyPropertyChanged(komisiKaryawanChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaPromoChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.NamaPromo);
        public DataWrapper<String> NamaPromo
        {
            get { return namaPromo; }
            set
            {
                namaPromo = value;
                NotifyPropertyChanged(namaPromoChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs potonganPromoChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.PotonganPromo);
        public DataWrapper<Int32> PotonganPromo
        {
            get { return potonganPromo; }
            set
            {
                potonganPromo = value;
                NotifyPropertyChanged(potonganPromoChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs nilaiKepuasanChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.NilaiKepuasan);
        public DataWrapper<Int32> NilaiKepuasan
        {
            get { return nilaiKepuasan; }
            set
            {
                nilaiKepuasan = value;
                NotifyPropertyChanged(nilaiKepuasanChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaFreeGiftChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.NamaFreeGift);
        public DataWrapper<String> NamaFreeGift
        {
            get { return namaFreeGift; }
            set
            {
                namaFreeGift = value;
                NotifyPropertyChanged(namaFreeGiftChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idJenisStokChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.IdJenisStok);
        public DataWrapper<Int32?> IdJenisStok
        {
            get { return idJenisStok; }
            set
            {
                idJenisStok = value;
                NotifyPropertyChanged(idJenisStokChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaJenisStokChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.NamaJenisStok);
        public String NamaJenisStok
        {
            get { return namaJenisStok; }
            set
            {
                namaJenisStok = value;
                NotifyPropertyChanged(namaJenisStokChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs jumlahFreeGiftChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.JumlahFreeGift);
        public DataWrapper<Int32> JumlahFreeGift
        {
            get { return jumlahFreeGift; }
            set
            {
                jumlahFreeGift = value;
                NotifyPropertyChanged(jumlahFreeGiftChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs waktuBuatChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.WaktuBuat);
        public DataWrapper<DateTime?> WaktuBuat
        {
            get { return waktuBuat; }
            set
            {
                waktuBuat = value;
                NotifyPropertyChanged(waktuBuatChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs waktuTungguChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.WaktuTunggu);
        public DataWrapper<DateTime?> WaktuTunggu
        {
            get { return waktuTunggu; }
            set
            {
                waktuTunggu = value;
                NotifyPropertyChanged(waktuTungguChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs waktuMulaiChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.WaktuMulai);
        public DataWrapper<DateTime?> WaktuMulai
        {
            get { return waktuMulai; }
            set
            {
                waktuMulai = value;
                NotifyPropertyChanged(waktuMulaiChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs waktuSelesaiChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.WaktuSelesai);
        public DataWrapper<DateTime?> WaktuSelesai
        {
            get { return waktuSelesai; }
            set
            {
                waktuSelesai = value;
                NotifyPropertyChanged(waktuSelesaiChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isBatalChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.IsBatal);
        public DataWrapper<Boolean> IsBatal
        {
            get { return isBatal; }
            set
            {
                isBatal = value;
                NotifyPropertyChanged(isBatalChangeArgs);
            }
        }
        #endregion

        #region Public.PreviousData && IsBusy
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isBusyChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.IsBusy);
        public bool IsBusy
        {
            get { return isBusy; }
            set
            {
                isBusy = value;
                NotifyPropertyChanged(isBusyChangeArgs);
            }
        }

        /// <summary>
        /// </summary>
        public int PreviousStatusTransaksiLayanan
        {
            get { return previousStatusTransaksiLayanan; }
            set
            {
                previousStatusTransaksiLayanan = value;
            }
        }
        #endregion

        #region Public.Cached Collection
        /// <summary>
        /// Returns cached collection of DataWrapperBase
        /// </summary>
        public IEnumerable<DataWrapperBase> CachedListOfDataWrappers
        {
            get { return cachedListOfDataWrappers; }
        }
        #endregion

        #region Public.DataVM
        #endregion

        #region Public.SummaryData
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs totalHargaLayananChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.TotalHargaLayanan);
        public Int32 TotalHargaLayanan
        {
            get
            {
                return HargaLayanan - PotonganPromo.DataValue;
            }
        }

        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs statusTransaksiLayananChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.StatusTransaksiLayanan);
        public int StatusTransaksiLayanan
        {
            get
            {
                int retval = 0;
                if (isBatal.DataValue)
                {
                    retval = STATUS_TRANSAKSILAYANAN_CANCELLED;
                }
                else if (waktuBuat.DataValue == null)
                {
                    retval = STATUS_TRANSAKSILAYANAN_UNKNOWN;
                }
                else if (waktuTunggu.DataValue == null)
                {
                    retval = STATUS_TRANSAKSILAYANAN_CREATED;
                }
                else if (waktuMulai.DataValue == null)
                {
                    retval = STATUS_TRANSAKSILAYANAN_WAIT;
                }
                else if (waktuSelesai.DataValue == null)
                {
                    retval = STATUS_TRANSAKSILAYANAN_BUSY;
                }
                else
                {
                    retval = STATUS_TRANSAKSILAYANAN_FINISHED;
                }
                return retval;
            }
        }
        #endregion

        #endregion

        #region Command Handlers
        /// <summary>
        /// </summary>
        private bool CanExecuteCabangLayananSelectCommand(Object args)
        {
            return !isBusy 
                && idTransaksiLayanan.DataValue == 0
                && CurrentViewMode == ViewMode.AddMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteCabangLayananSelectCommand(Object args)
        {
            CabangLayananSelectViewModel lcsvm = new CabangLayananSelectViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            bool? result = uiVisualizerService.ShowDialog("CabangLayananSelectPopup", lcsvm);
            if (result.HasValue && result.Value)
            {
                CabangLayananThumbnailViewModel lctvm = (CabangLayananThumbnailViewModel)
                    lcsvm.CabangLayanansCV.CurrentItem;
                this.IdLayanan.DataValue = lctvm.IdLayanan;
                this.NamaLayanan = lctvm.NamaLayanan;
                this.HargaLayanan = lctvm.Harga;
            }
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteKaryawanSelectCommand(Object args)
        {
            return !isBusy
                && (previousStatusTransaksiLayanan == STATUS_TRANSAKSILAYANAN_UNKNOWN
                    || previousStatusTransaksiLayanan == STATUS_TRANSAKSILAYANAN_CREATED
                    || previousStatusTransaksiLayanan == STATUS_TRANSAKSILAYANAN_WAIT)
                && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteKaryawanSelectCommand(Object args)
        {
            KaryawanSelectViewModel ksvm = new KaryawanSelectViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            ksvm.CriteriaSortIdLayanan = idLayanan.DataValue.HasValue ? idLayanan.DataValue.Value : 0 ;
            ksvm.StartLoading();
            bool? result = uiVisualizerService.ShowDialog("KaryawanSelectPopup", ksvm);
            if (result.HasValue && result.Value)
            {
                Console.WriteLine("masukkk");
                KaryawanThumbnailViewModel ktvm = (KaryawanThumbnailViewModel)
                    ksvm.KaryawansCV.CurrentItem;
                this.IdKaryawan.DataValue = ktvm.IdKaryawan;
                this.NamaKaryawan = ktvm.Nama;
            }
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteTransaksiLayananPreviousCommand(Object args)
        {
            return !isBusy 
                && (previousStatusTransaksiLayanan == STATUS_TRANSAKSILAYANAN_CREATED
                    || previousStatusTransaksiLayanan == STATUS_TRANSAKSILAYANAN_WAIT
                    || (previousStatusTransaksiLayanan == STATUS_TRANSAKSILAYANAN_BUSY
                        && StatusTransaksiLayanan == STATUS_TRANSAKSILAYANAN_FINISHED))
                && CurrentViewMode != ViewMode.ViewOnlyMode
                && waktuTunggu.DataValue.HasValue
                && !isBatal.DataValue;
        }
        /// <summary>
        /// </summary>
        private void ExecuteTransaksiLayananPreviousCommand(Object args)
        {
            if (waktuSelesai.DataValue.HasValue)
            {
                WaktuSelesai.DataValue = null;
            }
            else if (waktuMulai.DataValue.HasValue)
            {
                WaktuMulai.DataValue = null;
            }
            else if (waktuTunggu.DataValue.HasValue)
            {
                WaktuTunggu.DataValue = null;
            }
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteTransaksiLayananNextCommand(Object args)
        {
            return !isBusy 
                && CurrentViewMode != ViewMode.ViewOnlyMode 
                && !waktuSelesai.DataValue.HasValue
                && !isBatal.DataValue;
        }
        /// <summary>
        /// </summary>
        private void ExecuteTransaksiLayananNextCommand(Object args)
        {
            if (!waktuTunggu.DataValue.HasValue)
            {
                WaktuTunggu.DataValue = DateTime.Now;
            }
            else if (!waktuMulai.DataValue.HasValue)
            {
                WaktuMulai.DataValue = DateTime.Now;
            }
            else if (!waktuSelesai.DataValue.HasValue)
            {
                WaktuSelesai.DataValue = DateTime.Now;
            }
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteTransaksiLayananCancelCommand(Object args)
        {
            return !isBusy
                && StatusTransaksiLayanan != STATUS_TRANSAKSILAYANAN_FINISHED
                && previousStatusTransaksiLayanan != STATUS_TRANSAKSILAYANAN_CANCELLED
                && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteTransaksiLayananCancelCommand(Object args)
        {
            Mediator.Instance.NotifyColleagues("TryRemoveTransaksiLayanan", this);
        }

        /// <summary>
        /// </summary>
        private bool CanExecutePromoSelectCommand(Object args)
        {
            return !isBusy
                && StatusTransaksiLayanan == STATUS_TRANSAKSILAYANAN_FINISHED
                && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecutePromoSelectCommand(Object args)
        {
            PromoSelectViewModel psvm = new PromoSelectViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            if (idLayanan.DataValue.HasValue)
            {
                psvm.SetCriteria(idLayanan.DataValue.Value);
            }
            else
            {
                psvm.SetCriteria(0);
            }
            bool? result = uiVisualizerService.ShowDialog("PromoSelectPopup", psvm);
            if (result.HasValue && result.Value)
            {
                PromoThumbnailViewModel ptvm = (PromoThumbnailViewModel)
                    psvm.DataCV.CurrentItem;
                this.NamaPromo.DataValue = ptvm.Nama;
                if (ptvm.IsPersentase)
                {
                    this.PotonganPromo.DataValue = (int)(ptvm.PersentasePromo * (double)HargaLayanan);
                }
                else
                {
                    this.potonganPromo.DataValue = ptvm.NominalPromo;
                }
            }
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteFreeGiftSelectCommand(Object args)
        {
            return !isBusy
                && StatusTransaksiLayanan == STATUS_TRANSAKSILAYANAN_FINISHED
                && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteFreeGiftSelectCommand(Object args)
        {
            FreeGiftSelectViewModel fsvm = new FreeGiftSelectViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            fsvm.SetCriteria(idLayanan.DataValue);
            bool? result = uiVisualizerService.ShowDialog("FreeGiftSelectPopup", fsvm);
            if (result.HasValue && result.Value)
            {
                FreeGiftThumbnailViewModel ftvm = (FreeGiftThumbnailViewModel)
                    fsvm.FreeGiftsCV.CurrentItem;
                this.namaFreeGift.DataValue = ftvm.Nama;
                this.IdJenisStok.DataValue = ftvm.IdJenisStok;
                this.JumlahFreeGift.DataValue = ftvm.Jumlah;
            }
        }
        #endregion

        #region Change Callbacks
        /// <summary>
        /// </summary>
        private void HargaLayananChangeCallback()
        {
            NotifyPropertyChanged(totalHargaLayananChangeArgs);
            Mediator.Instance.NotifyColleagues<Boolean>("SummaryChangeMessage", true);
        }
        /// <summary>
        /// </summary>
        private void PotonganPromoChangeCallback()
        {
            NotifyPropertyChanged(totalHargaLayananChangeArgs);
            Mediator.Instance.NotifyColleagues<Boolean>("SummaryChangeMessage", true);
        }

        /// <summary>
        /// </summary>
        private void WaktuTungguChangeCallback()
        {
            NotifyPropertyChanged(statusTransaksiLayananChangeArgs);
        }
        /// <summary>
        /// </summary>
        private void WaktuMulaiChangeCallback()
        {
            NotifyPropertyChanged(statusTransaksiLayananChangeArgs);
        }
        /// <summary>
        /// </summary>
        private void WaktuSelesaiChangeCallback()
        {
            NotifyPropertyChanged(statusTransaksiLayananChangeArgs);
        }
        /// <summary>
        /// </summary>
        private void IsBatalChangeCallback()
        {
            NotifyPropertyChanged(statusTransaksiLayananChangeArgs);
        }
        #endregion

        #region Private Methods
        #endregion

        #region Overrides
        static PropertyChangedEventArgs isValidChangeArgs =
            ObservableHelper.CreateArgs<TransaksiLayananViewModel>(x => x.IsValid);

        public override bool IsValid
        {
            get
            {
                //return base.IsValid and use DataWrapperHelper, if you are
                //using DataWrappers
                return base.IsValid &&
                    DataWrapperHelper.AllValid(cachedListOfDataWrappers);
            }

        }

        public bool IsDirty
        {
            get
            {
                return DataWrapperHelper2.SomeDirty(cachedListOfDataWrappers);
            }
        }

        public override string ToString()
        {
            return String.Format("TransaksiLayananViewModel {0}", this.idTransaksiLayanan);
        }
        #endregion

        #region EditableValidatingViewModelBase overrides
        protected override void OnBeginEdit()
        {
            base.OnBeginEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call BeginEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetBeginEdit(cachedListOfDataWrappers);
        }

        /// <summary>
        /// Override hook which allows us to also put any child 
        /// EditableValidatingViewModelBase objects into the EndEdit state
        /// </summary>
        protected override void OnEndEdit()
        {
            base.OnEndEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call CancelEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetEndEdit(cachedListOfDataWrappers);
        }

        /// <summary>
        /// Override hook which allows us to also put any child 
        /// EditableValidatingViewModelBase objects into the CancelEdit state
        /// </summary>
        protected override void OnCancelEdit()
        {
            base.OnCancelEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call CancelEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetCancelEdit(cachedListOfDataWrappers);
        }
        #endregion
    }
}
